// SessionFriendItem.hpp
// Created by Limou on 24-10-5.

#ifndef FRONTEND_SESSIONFRIENDITEM_HPP
#define FRONTEND_SESSIONFRIENDITEM_HPP

// >>> class SessionFriendItem begin: 普通滚动区域内的子项类 >>>
namespace chat_system::subassembly {
    class SessionFriendItem : public QWidget {
    Q_OBJECT

    protected:
        // 部件
        QWidget *owner_; // 指向滚动区域的指针 NOTE: 有可能需要使用父类指针成员
        QGridLayout *layout_; // 布局管理
        QPushButton *avatarBtn_; // 头像按钮
        QLabel *nameLbl_; // 标题
        QLabel *textLbl_; // 描述

        // 数据
        bool selected_; // 是否被选中
        QString name_; // 名称
        QString text_; // 描述
        QIcon avatar_; // 头像

    public:
        // 构造方法
        explicit SessionFriendItem(
            QWidget *owner,
            const QIcon &avatar,
            const QString &name,
            const QString &text
        )
        : owner_(owner)
        , layout_(new QGridLayout(this)) // TODO: 这个还不能随意更改, 后面得子类有用这个继承成员的...
        , avatarBtn_(new QPushButton(this))
        , nameLbl_(new QLabel(this))
        , textLbl_(new QLabel(this))
        , selected_(false)
        , avatar_(avatar)
        , name_(name)
        , text_(text) {
            this->setElement(); // 设置组件
            this->setElementStyle(); // 设置组件样式
            this->setElementLayout(); // 设置组件布局
            this->setElementSignalSlot(); // 设置信号槽
        }

        // 析构方法
        ~SessionFriendItem() override = default;

    public:
        // 手动高亮选项
        void highlight() {
            selectHighlight();
        }

    protected:
        // 会话事件的处理
        void paintEvent(QPaintEvent *event) override {
            (void)event; // 避免警告
            QStyleOption opt; // 创建可以存储绘制部件时所需的各种信息的对象
            opt.initFrom(this); // 将当前部件的属性初始化到 opt 对象中
            QPainter p(this); // 创建了一个 QPainter 对象 p 并将其与当前部件关联
            style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); // TODO: ? 老实说, 这里没看懂，以后研究叭...
        }

        // 鼠标事件的处理
        void mousePressEvent(QMouseEvent *event) override {
            (void)event; // 避免警告
            this->selectHighlight(); // 高亮选项
            common::Tools::getInstance()->getLogger()->trace("{0} {1} The SessionFriendItem was clicked", __FILE__, __LINE__);
        }

        // 进入事件的处理
        void enterEvent(QEnterEvent *event) override {
            (void)event; // 避免警告
            if (!this->selected_) {
                this->setStyleSheet("QWidget { background: rgb(220, 221, 221); }");
            }
        }

        // 离开事件的处理 // NOTE: 这种离开和进入的设计比信号槽好多了...可以迁移这个代码
        void leaveEvent(QEvent *event) override {
            (void) event;
            if (!this->selected_) {
                this->setStyleSheet("QWidget { background: rgb(231, 230, 230); }");
            }
        }

    private:
        // 设置组件方法
        void setElement() {
            // 设置本部件的样式
            this->setFixedHeight(64);

            // 设置会话图标按钮
            avatarBtn_->setFixedSize(40, 40);
            avatarBtn_->setIconSize(QSize(40, 40));
            avatarBtn_->setIcon(avatar_);
            avatarBtn_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); // 设置尺寸策略, 这里设置的是水平方向和垂直方向都是固定的, 不会随着父元素内容自动调整大小

            // 设置会话标题
            nameLbl_->setText(name_);
            nameLbl_->setFixedHeight(35);
            nameLbl_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // 设置尺寸策略, 这里设置的是水平方向由 Qt 自己决定, 垂直方向都是固定的, 不会随着父元素内容自动调整大小

            // 设置描述
            textLbl_->setText(text_);
            textLbl_->setFixedHeight(15);
            textLbl_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // 设置尺寸策略, 这里设置的是水平方向由 Qt 自己决定, 垂直方向都是固定的, 不会随着父元素内容自动调整大小
        }

        // 设置组件样式方法
        void setElementStyle() {
            this->setStyleSheet("QWidget { background: rgb(231, 230, 230); }"); // NOTE: 如果是 QWidget 的子类, 就需要依据文档重写一个方法, 才能使这里的 QSS 生效
            avatarBtn_->setStyleSheet("QPushButton { border: none; } ");
            nameLbl_->setStyleSheet(" QLabel { color: black; font-size: 15px; font-weight: 500; } ");
            textLbl_->setStyleSheet(" QLabel { color: grey; font-size: 12px; font-weight: 400; } ");
        }

        // 设置组件布局方法
        void setElementLayout() {
            // 设置布局管理
            layout_->setContentsMargins(10, 0, 0, 0);
            layout_->setHorizontalSpacing(10);
            layout_->setVerticalSpacing(0);
            this->setLayout(layout_);

            // 添加组件到布局管理器中 // TODO: 可以简化一下下面的布局管理为子函数
            layout_->addWidget(avatarBtn_, 0, 0, 2, 2); // (0, 0) 处占据 2 列 2 行
            layout_->addWidget(nameLbl_, 0, 2, 1, 8); // (0, 2) 处占据 1 列 1 行
            layout_->addWidget(textLbl_, 1, 2, 1, 8); // (1, 2) 处占据 1 列 1 行
        }

        // 设置信号槽
        void setElementSignalSlot() {

        }

        // 鼠标点击选项时高亮的子逻辑
        void selectHighlight() {
            // 遍历其他未选中元素消除高亮
            auto brothers = this->parentWidget()->children();
            for (auto brother : brothers) {
                if (brother->isWidgetType()) { // 如果是 Widget 类型就做以下事情
                    SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(brother); // TODO: 可以稍微探究这里
                    if(item->selected_) { // 取消凸显状态和颜色
                        item->setStyleSheet("QWidget { background: rgb(231, 230, 230); }");
                        item->selected_ = false;
                    }
                }
            }

            // 高亮用户选中的选项
            this->setStyleSheet("QWidget { background: rgb(211, 210, 210); }");
            this->selected_ = true; // 同时更改状态表示选中
        }
    }; // class SessionFriendItem end
} // namespace chat_system::subassembly end
// <<< class SessionFriendItem end <<<

// >>> class SessionItem begin: 会话滚动区域的子项类 >>>
namespace chat_system::subassembly {
    class SessionItem : public SessionFriendItem { // TODO: 后期考虑分文件
    Q_OBJECT

    private:
        QString chatSessionId_; // 会话 id

    public:
        SessionItem(
            QWidget *const owner,
            const QString &chatSessionId,
            const QIcon &avtar,
            const QString &name,
            const QString &lastMessage
        )
        : SessionFriendItem(owner, avtar, name, lastMessage)
        , chatSessionId_(chatSessionId) {
            this->setElement(); // 设置组件
            this->setElementStyle(); // 设置组件样式
            this->setElementLayout(); // 设置组件布局
            this->setElementSignalSlot(); // 设置信号槽
        }

    protected:
        void mousePressEvent(QMouseEvent* event) override {
            SessionFriendItem::mousePressEvent(event);
            common::Tools::getInstance()->getLogger()->trace("{0} {1} The SessionItem was clicked signal~", __FILE__, __LINE__);
            emit this->SessionItemIsClicked(chatSessionId_);
        }

    signals:
        void SessionItemIsClicked(const QString& chatSessionId);

    private:
        // 设置组件方法
        void setElement() {

        }

        // 设置组件样式方法
        void setElementStyle() {

        }

        // 设置组件布局方法
        void setElementLayout() {

        }

        // 设置信号槽
        void setElementSignalSlot() {

        }
    }; // class SessionItem end
} // namespace chat_system::subassembly end
// <<< class SessionItem end <<<

// >>> class FriendItem begin: 好友滚动区域的子项类 >>>
namespace chat_system::subassembly {
    class FriendItem : public SessionFriendItem { // TODO: 后期考虑分文件
    Q_OBJECT

    private:
        QString userId_; // 好友 id

    public:
        FriendItem(
            QWidget *const owner,
            const QString &userId,
            const QIcon &avtar,
            const QString &name,
            const QString &personalSignature
        )
        : SessionFriendItem(owner, avtar, name, personalSignature)
        , userId_(userId) {
            this->setElement(); // 设置组件
            this->setElementStyle(); // 设置组件样式
            this->setElementLayout(); // 设置组件布局
            this->setElementSignalSlot(); // 设置信号槽
        }

    private:
        // 设置组件方法
        void setElement() {

        }

        // 设置组件样式方法
        void setElementStyle() {

        }

        // 设置组件布局方法
        void setElementLayout() {

        }

        // 设置信号槽
        void setElementSignalSlot() {

        }
    }; // class FriendItem end
} // namespace chat_system::subassembly end
// <<< class FriendItem end <<<

// >>> class ApplyForItem begin: 申请滚动区域的子项类 >>>
namespace chat_system::subassembly {
    class ApplyForItem : public SessionFriendItem { // TODO: 后期考虑分文件
    Q_OBJECT
    private:
        QString userId_; // 好友 id
        QPushButton* agreeBtn_; // 同意按钮
        QPushButton* refuseBtn_; // 同意按钮

    public:
        ApplyForItem( // TODO: 这里可以添加申请文本
            QWidget* const owner,
            const QString& userId,
            const QIcon& avtar,
            const QString& name
        )
        : SessionFriendItem(owner, avtar, name, "")
        , userId_(userId)
        , agreeBtn_(new QPushButton(this))
        , refuseBtn_(new QPushButton(this)) {
        this->setElement(); // 设置组件
        this->setElementStyle(); // 设置组件样式
        this->setElementLayout(); // 设置组件布局
        this->setElementSignalSlot(); // 设置信号槽
    }

    private:
        // 设置组件方法
        void setElement() {
            // 设置同意按钮
            agreeBtn_->setText("同意");
            agreeBtn_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // 设置尺寸策略, 这里设置的是水平方向由 Qt 自己决定, 垂直方向都是固定的, 不会随着父元素内容自动调整大小

            // 设置拒绝按钮
            refuseBtn_->setText("拒绝");
            refuseBtn_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // 设置尺寸策略, 这里设置的是水平方向由 Qt 自己决定, 垂直方向都是固定的, 不会随着父元素内容自动调整大小
        }

        // 设置组件样式方法
        void setElementStyle() {
            agreeBtn_->setStyleSheet("QPushButton { color: green; font-size: 10px; } ");
            refuseBtn_->setStyleSheet("QPushButton { color: red; font-size: 10px; } ");
        }

        // 设置组件布局方法
        void setElementLayout() {
            // 移除消息预览标签
            auto layout_ = dynamic_cast<QGridLayout*>(this->layout());
            layout_->removeWidget(textLbl_); // NOTE: 无需释放内存
            layout_->addWidget(agreeBtn_, 1, 2, 1, 1); // (1, 2) 处占据 1 列 1 行
            layout_->addWidget(refuseBtn_, 1, 3, 1, 1); // (2, 2) 处占据 1 列 1 行
        }

        // 设置信号槽
        void setElementSignalSlot() {

        }
    }; // class ApplyForItem end
} // namespace chat_system::subassembly end
// <<< class SessionFriendArea end <<<

#endif //FRONTEND_SESSIONFRIENDITEM_HPP
